<template>
  <div class="myTable" style="width: 100%; height: 100%">
    <div class="tableTool">
      <div class="defaultTool">
        <el-button
          v-if="props.defaultTool.indexOf('checkAll') !== -1"
          class="g-minibutton"
          :icon="checkAll ? 'Close' : 'Check'"
          @click="checkAllEvent"
        >
          {{ checkAll ? "取消全选" : "全选" }}
        </el-button>
        <el-button
          v-for="(item, index) in showButtonList"
          :key="index"
          class="g-minibutton"
          :icon="item.icon"
          @click="item.event"
        >
          {{ item.label }}
        </el-button>
      </div>
      <div class="diyTool">
        <slot name="tableTool"></slot>
      </div>
    </div>
    <el-table
      ref="myTable"
      :data="table.tableData"
      :height="calcElTableHeight || 300"
      :highlight-current-row="true"
      border
      v-bind="$attrs"
      @mouseup="mouseUp"
      @mousedown="mouseDown"
      @dragenter="dragEnter"
      @dragleave="removeClass"
      @drop="removeClass"
      @cell-click="cellClick"
      @cell-dblclick="dblClick"
      @select="tableSelect"
      @select-all="tableSelectAll"
    >
      <el-table-column
        v-if="props.selection"
        type="selection"
        width="60"
        :align="'center'"
      ></el-table-column>
      <el-table-column
        v-if="props.serialNumber"
        label="Id"
        type="index"
        width="60"
        :align="'center'"
      ></el-table-column>
      <table-column
        v-for="item in table.tableHeaders"
        :key="item.prop"
        :data="item"
        @changed="changed"
      >
        <template v-for="(item, key) in $slots" :key="key" #[key]="scoped">
          <slot :name="key" :data="scoped.data"></slot>
        </template>
      </table-column>
    </el-table>
    <el-pagination
      v-if="isPaging"
      v-model:current-page="table.currentPage"
      v-model:page-size="table.pageSize"
      :page-sizes="pageNumber"
      :background="true"
      :layout="layout"
      :total="table.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
  <my-dialog
    title="自定义列"
    :isShow="customShow"
    @close="customShow = false"
    width="300px"
  >
    <el-tree
      :data="customTree.data"
      :props="{ children: 'children', label: 'label' }"
      :node-key="'prop'"
      show-checkbox
      default-expand-all
      :default-checked-keys="customTree.defaultCheckedKeys"
      @check-change="handleCheck"
    ></el-tree>
  </my-dialog>
</template>

<script setup>
import {
  defineProps,
  reactive,
  onMounted,
  onUnmounted,
  ref,
  watchEffect,
  getCurrentInstance,
  defineEmits,
  computed,
  nextTick,
  defineExpose,
  watch,
} from "vue";
import TableColumn from "./TableColumn";
import request from "@/api/request";
import { ElMessage } from "element-plus";
const props = defineProps({
  height: {
    type: [Number, String],
  },
  isDrag: {
    type:Boolean,
    default: false,
  },
  tableData: {
    type: Array,
    default() {
      return [];
    },
  },
  tableHeader: Array,
  total: {
    type: Number,
    default: 0,
  },
  layout: {
    type: String,
    default() {
      return "total, sizes, prev, pager, next, jumper";
    },
  },
  pageNumber: {
    type: Array,
    default() {
      return [20, 50, 80, 120];
    },
  },
  serialNumber: {
    type: Boolean,
    default: false,
  },
  url: {
    type: String,
    default: "",
  },
  params: {
    type: Object,
    default() {
      return {};
    },
  },
  isPaging: {
    type: Boolean,
    default: false,
  },
  // 分页模式 remote/local
  pageType: {
    type: String,
    default: "remote",
  },
  // 勾选状态冻结(跨页勾选,仅本地分页模式下生效)
  checkFrozen: {
    type: Boolean,
    default: false,
  },
  selection: {
    type: Boolean,
    default: false,
  },
  /* 操作按钮 */
  defaultTool: {
    type: Array,
    default: () => ["checkAll", "addUser", "exportExcel"],
  },
  // 自定义列key
  customKey: {
    type: String,
  },
});
const emits = defineEmits([
  "sizeChange",
  "currentChange",
  "toolButtonCheckAll",
  "tableSelect",
  "tableSelectAll",
]);
onMounted(() => {
  if (props.defaultTool.indexOf("customColumn") !== -1 && !props.customKey) {
    console.warn("请传入key");
    table.tableHeaders = props.tableHeader;
  } else {
    customInit();
  }
  table.flatHeader = $util.flattenArray(props.tableHeader);
  document.addEventListener("dragover", function (event) {
    event.preventDefault();
  });
  if (!props.height) {
    calcHeight();
  }
});
const inst = getCurrentInstance();
const vueProperty = inst.appContext.config.globalProperties;
const $util = vueProperty.$util;
const myTable = ref(null);
let table = reactive({
  tableHeaders: [],
  flatHeader: [], // 扁平化表头
  tableData: [], //表格展示数据
  dataList: [], // 表格所有数据,主要针对于本地分页
  currentPage: undefined,
  pageSize: undefined,
});
//* 表格数据赋值 */
watchEffect(() => {
  table.dataList = props.tableData;
});

/*  表格拖拽 */
// 拖拽行信息
let startDrag = reactive({ index: null, data: [] });
// 拖拽到哪一行的信息
let endDrag = reactive({ index: null, data: [] });
const mouseDown = (e) => {
  if (
    e.target.parentNode.parentNode.parentNode.parentNode.className !==
      "el-table__body" ||
    e.target.parentNode.parentNode.nodeName !== "TR" ||
    !props.isDrag
  )
    return;
  // 将可拖拽属性设为true
  e.target.parentNode.parentNode.draggable = true;
  // 开始拖拽
  e.target.parentNode.parentNode.ondragstart = (e) => {
    startDrag.index = e.target.rowIndex;
  };
};
const mouseUp = (e) => {
  e.target.parentNode.parentNode.draggable = false;
};
const dragEnter = (e) => {
  if (e.target.parentNode.parentNode.nodeName !== "TR") return;
  e.target.parentNode.parentNode.draggable = false;
  e.target.parentNode.parentNode.classList.add("dragBgc");
  // 交换数据位置
  endDrag.index = e.target.parentNode.parentNode.rowIndex;
  endDrag.data = table.tableData[endDrag.index];
  startDrag.data = table.tableData[startDrag.index];
  table.tableData[startDrag.index] = endDrag.data;
  table.tableData[endDrag.index] = startDrag.data;
  // 将上次结束的索引,作为重新开始的索引
  startDrag.index = endDrag.index;
};
const removeClass = (e) => {
  e.target.parentNode.parentNode.classList.remove("dragBgc");
};
const cellClick = (row, column, cell, event) => {};

/**
 * 可编辑单元格
 */
let columnData = reactive({ data: {} });
const dblClick = (row, column, cell, event) => {
  let isEdit = table.flatHeader.find(
    (item) => item.prop === column.property
  )?.edit;
  // edit支持boolen和function格式
  if (typeof isEdit === "function") {
    isEdit = isEdit(row, column, cell, event);
  }
  if (!isEdit) return;
  row.isEdit = true;
  column.isEdit = true;
  columnData.data = column;
};
// 失去焦点 插槽数据中的column不是响应式数据,所以直接修改(scoped.column.isEdit = false)无效
const changed = (scoped) => {
  scoped.row.isEdit = false;
  columnData.data.isEdit = false;
};

/* 请求数据 */
const requestTableData = (url, params) => {
  request.post(url, params).then((res) => {
    if (res.code !== 200) {
      ElMessage.error("查询数据失败");
      return;
    }
    table.total = res.total;
    handlePageData(res.data);
  });
};
// 表格查询统一接口,子组件调用
const query = () => {
  if (table.dataList.length) {
    handlePageData(table.dataList);
  } else {
    requestTableData(props.url, getParams());
  }
};
// 获取请求参数
const getParams = () => {
  let params = {};
  if (props.isPaging) {
    params = {
      ...props.params,
      limit: table.pageSize,
      page: table.currentPage,
    };
  } else {
    params = props.params;
  }
  return params;
};
// 处理分页
const handlePageData = (data) => {
  if (props.isPaging) {
    table.currentPage = table.currentPage ? table.currentPage : 1;
    table.pageSize = table.pageSize ? table.pageSize : props.pageNumber[0];
    if (props.pageType === "local") {
      handleLocalPageData(data);
    } else {
      handleRemotePageData(data);
    }
  } else {
    table.dataList = data;
    table.tableData = data;
  }
};
// 处理本地分页
const handleLocalPageData = (tableData) => {
  if (checkAll.value) {
    myTable.value.toggleAllSelection();
  }
  table.total = tableData.length;
  const currentPage = table.currentPage;
  const pageSize = table.pageSize;
  table.tableData = tableData.slice(
    (currentPage - 1) * pageSize,
    currentPage * pageSize
  );
};
// 处理远程分页
const handleRemotePageData = (tableData) => {
  table.dataList = tableData;
  table.tableData = tableData;
};
// 切换一页展示数量
const handleSizeChange = (value) => {
  query();
  setTableCheckStatus()
  emits("sizeChange", value);
};
// 切换页码
const handleCurrentChange = (value) => {
  query();
  emits("currentChange", value);
};
// 冻结表格勾选状态
const setTableCheckStatus = (data) => {
 console.log(tableCheckList.value)
};

/**
 * 监听dom元素高度变化
 */
const calcElTableHeight = ref(300);
let observer;
const calcHeight = () => {
  nextTick(() => {
    const table = document.querySelector(".myTable");
    observer = new ResizeObserver((e) => {
      calcElTableHeight.value = `calc(100% - 90px)`;
      myTable.value.doLayout();
    });
    observer.observe(table);
  });
};
/**
 * 表格工具栏事件
 * @param *
 * @return null
 */
const checkAll = ref(false);
const buttonList = [
  {
    label: "自定义列",
    icon: "tools",
    class: "",
    event: () => handleCustom(),
    name: "customColumn",
  },
  {
    label: "新增用户",
    icon: "CirclePlus",
    class: "",
    event: "",
    name: "addUser",
  },
  { label: "批量添加用户", icon: "Upload", class: "", event: "" },
  {
    label: "导出用户数据",
    icon: "Download",
    class: "",
    event: "",
    name: "exportExcel",
  },
  { label: "批量删除用户", icon: "Delete", class: "", event: "" },
];
/* 剔除不展示的按钮 */
const showButtonList = computed(() => {
  return buttonList.filter((item) => {
    return props.defaultTool.some((name) => name == item.name);
  });
});
// 存储选中数据 所有事件通用包括工具栏全选
const tableCheckList = ref([]);
// 工具栏全选事件
const checkAllEvent = () => {
  checkAll.value = !checkAll.value;
  tableCheckList.value = checkAll.value ? table.tableData : [];
  table.tableData.forEach((row) => {
    myTable.value.toggleRowSelection(row, checkAll.value);
  });
  emits("toolButtonCheckAll", checkAll.value, table.tableData);
};
// 单选事件
const tableSelect = (checkList, item) => {
  const isCheck = checkList.indexOf(item) !== -1;
  checkAll.value = false;
  tableCheckList.value = checkList;
  emits("tableSelect", checkList, isCheck);
};
// 单页全选事件
const tableSelectAll = (checkList) => {
  const isCheck = checkList.length > 0;
  tableCheckList.value = checkList;
  if (!isCheck) {
    checkAll.value = false;
  }
  emits("tableSelectAll", checkList, isCheck);
};
// 获取所选中数据
const gettableCheckList = () => {
  return tableCheckList.value;
};
const customShow = ref(false);
// 自定义列
const handleCustom = () => {
  customShow.value = true;
};
let customTree = reactive({
  data: [],
  defaultCheckedKeys: [],
});

const customInit = () => {
  let headers = [];
  customTree.data = props.tableHeader;
  // console.log(props.tableHeader);
  if (sessionStorage.getItem(props.customKey)) {
    let customList = JSON.parse(sessionStorage.getItem(props.customKey));
    customTree.defaultCheckedKeys = customList;
    filterHeader(customList, props.tableHeader, headers);
  } else {
    let checkList = [];
    handleCheckKeys(props.tableHeader, checkList);
    // console.log(checkList);
    customTree.defaultCheckedKeys = checkList;
    sessionStorage.setItem(
      props.customKey,
      JSON.stringify(customTree.defaultCheckedKeys)
    );
    filterHeader(customTree.defaultCheckedKeys, props.tableHeader, headers);
  }
  table.tableHeaders = headers;
};
const handleCheckKeys = (header, result = []) => {
  header.forEach((item) => {
    if (item.children) {
      // result.push(item.prop)
      handleCheckKeys(item.children, result);
    } else {
      if (!item.initHide) {
        result.push(item.prop);
      }
    }
  });
};
const filterHeader = (keys, header, result = []) => {
  header.forEach((item) => {
    try {
      if (item.children && Array.isArray(item.children)) {
        const newItem = { ...item };
        newItem.children = filterHeader(keys, item.children);
        if (newItem.children.length > 0 || keys.includes(item.prop)) {
          result.push(newItem);
        }
      } else if (keys.includes(item.prop)) {
        result.push(item);
      }
    } catch (error) {
      console.error("Error filtering header:", error);
    }
  });
  return result;
};
const handleCheck = (data, isCheck) => {
  let customList = JSON.parse(sessionStorage.getItem(props.customKey));
  // console.log(data, isCheck, customList);
  let index = customList.findIndex((item) => item === data.prop);
  if (isCheck) {
    if (index == -1) {
      customList.push(data.prop);
    }
  } else {
    if (index != -1) {
      customList.splice(index, 1);
    } else {
      customList.push(data.prop);
    }
  }
  sessionStorage.setItem(props.customKey, JSON.stringify(customList));
  let headers = [];
  filterHeader(customList, props.tableHeader, headers);
  table.tableHeaders = headers;
};
onUnmounted(() => {
  if (!observer) return;
  observer.disconnect();
});
defineExpose({
  query,
});
</script>

<style lang="scss">
.myTable {
  overflow: hidden;
}

.el-table {
  overflow: hidden;
  border: 1px solid #ebeef5;
  // color: red;
  font-size: 12px;
}

.el-table__header {
  margin: auto;
}

.el-table__header .el-table__cell {
  color: black;
  background-color: #f5f7fa !important;
}

.el-table td.el-table__cell,
.el-table th.el-table__cell.is-leaf {
  border-bottom: 1px solid #ebeef5;
}

.el-table--border .el-table__cell {
  border-right: 1px solid #ebeef5;
}

.el-table--border th.el-table__cell {
  border-bottom: 1px solid #ebeef5;
}

.el-table .el-table__cell {
  padding: 4px 0;
}

.dragBgc {
  background-color: #42b983 !important;
  color: white;
}

.el-pagination {
  margin: 15px 0;
  display: flex;
  justify-content: right;
}

.el-table__inner-wrapper {
  height: 100% !important;
}

.tableTool {
  width: 100%;
  height: 35px;
  display: flex;
  justify-content: left;
  align-items: center;
}

.diyTool {
  margin-left: 12px;
}
</style>
